package com.base.cn.platform.os.service.course.catalog;

import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.Pagination;
import com.base.cn.platform.os.common.number.AmountUtils;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.course.CourseType;
import com.base.cn.platform.os.common.utils.course.MaterialType;
import com.base.cn.platform.os.dao.course.catalog.CourseCatalogDao;
import com.base.cn.platform.os.entity.course.catalog.CourseCatalog;
import com.base.cn.platform.os.entity.course.catalog.CourseCatalogCondition;
import com.base.cn.platform.os.entity.course.catalog.CourseLiveReminder;
import com.base.cn.platform.os.entity.course.cou.Course;
import com.base.cn.platform.os.entity.course.cou.buy.CourseBuyRecord;
import com.base.cn.platform.os.entity.course.cou.packageCou.PackageCourse;
import com.base.cn.platform.os.entity.course.cou.record.CourseLearnFlow;
import com.base.cn.platform.os.entity.course.cou.record.CoursePlayRecord;
import com.base.cn.platform.os.entity.course.material.CouMaterial;
import com.base.cn.platform.os.entity.course.mould.CouMould;
import com.base.cn.platform.os.entity.course.mould.CouMouldMaterial;
import com.base.cn.platform.os.service.course.cou.CourseBiz;
import com.base.cn.platform.os.service.course.cou.buy.CourseBuyRecordBiz;
import com.base.cn.platform.os.service.course.cou.packageCou.PackageCourseBiz;
import com.base.cn.platform.os.service.course.cou.record.CoursePlayRecordBiz;
import com.base.cn.platform.os.service.course.material.CouMaterialBiz;
import com.base.cn.platform.os.service.course.mould.CouMouldBiz;
import com.base.cn.platform.os.service.exam.question.ExamQuestionsService;
import com.base.cn.platform.os.service.exam.record.ExamRecordService;
import com.base.cn.platform.os.service.manage.loreset.LoresetPointService;
import com.base.cn.platform.os.service.manage.loreset.LoresetService;
import com.base.cn.platform.os.service.manage.teacher.SysTeacherService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 课程目录Biz
 *
 * @author s.li
 * @create 2018-04-25-19:44
 */
@Service
public class CourseCatalogBiz extends BaseBiz<CourseCatalog, CourseCatalogDao> {

    @Autowired
    private CouMaterialBiz couMaterialBiz;
    @Autowired
    private CouMouldBiz couMouldBiz;
    @Autowired
    private CourseBiz courseBiz;
    @Autowired
    private ExamQuestionsService examQuestionsService;
    @Autowired
    private LoresetService loresetService;
    @Autowired
    private LoresetPointService loresetPointService;
    @Autowired
    private CoursePlayRecordBiz coursePlayRecordBiz;
    @Autowired
    private CourseCatalogDao courseCatalogDao;
    @Autowired
    private SysTeacherService sysTeacherService;
    @Autowired
    private ExamRecordService examRecordService;
    @Autowired
    private CourseBuyRecordBiz courseBuyRecordBiz;
    @Autowired
    private PackageCourseBiz packageCourseBiz;

    /**
     * 调整节点排序
     *
     * @param currentId   要操作的节点ID
     * @param currentSort 操作的节点的新排序
     * @param oldId       被替换节点的ID
     * @param oldSort     被替换节点的排序
     */
    public void updateNodeSort(BigDecimal currentId, int currentSort, BigDecimal oldId, int oldSort) {
        List<CourseCatalog> courseCatalogList = new ArrayList<>();

        CourseCatalog currentCatalog = new CourseCatalog();
        currentCatalog.setId(currentId);
        currentCatalog.setSort(currentSort);

        courseCatalogList.add(currentCatalog);

        CourseCatalog oldCatalog = new CourseCatalog();
        oldCatalog.setId(oldId);
        oldCatalog.setSort(oldSort);

        courseCatalogList.add(oldCatalog);

        this.updateBatch(courseCatalogList);
    }

    /**
     * 查询目录数量
     *
     * @param condition 查询条件
     * @return 数量
     */
    public BigDecimal getCourseCatalogCount(CourseCatalogCondition condition) {
        String whereSql = this.getWhereSql(condition);
        return this.count(whereSql);
    }

    /**
     * 查询用户课程最后学习目录Map
     *
     * @param courseIds 课程ID串
     * @return 目录Map Map<BigDecimal,CourseCatalog>
     */
    public Map<BigDecimal, CourseCatalog> findLiveCourseListNodeMap(String courseIds) {
        List<CourseCatalog> courseCatalogList = this.findLiveCourseListNodes(courseIds);
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            return courseCatalogList.stream().collect(Collectors.toMap(e -> e.getCourseId(), e -> e));
        }
        return null;
    }

    /**
     * 查询用户课程最后学习目录列表
     *
     * @param courseIds 课程ID串
     * @return 目录列表 List<CourseCatalog>
     */
    public List<CourseCatalog> findLiveCourseListNodes(String courseIds) {
        return courseCatalogDao.findLiveCourseListNodes(CourseCatalog.class, courseIds);
    }

    /**
     * 查询用户课程最后学习目录Map
     *
     * @param userId       用户ID
     * @param buyCourseIds 用户购买的课程ID串
     * @return Map<BigDecimal                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               CourseCatalog>
     */
    public Map<BigDecimal, CourseCatalog> findUserCourseLastStudyCatalogMap(BigDecimal userId, String buyCourseIds) {
        List<CourseCatalog> courseCatalogList = findUserCourseLastStudyCatalogList(userId, buyCourseIds);
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            return courseCatalogList.stream().collect(Collectors.toMap(e -> e.getCourseId(), e -> e, (oldValue, newValue) -> oldValue));
        }
        return null;
    }

    /**
     * 查询用户课程最后学习目录列表
     *
     * @param userId       用户ID
     * @param buyCourseIds 用户购买的课程ID串
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> findUserCourseLastStudyCatalogList(BigDecimal userId, String buyCourseIds) {
        Map<String, Object> params = new HashMap<>();
        params.put("userId", userId);
        params.put("buyCourseIds", buyCourseIds);
        return courseCatalogDao.findUserCourseLastStudyCatalogList(CourseCatalog.class, params);
    }

    /**
     * 保存课程目录数据
     *
     * @param courseCatalog 课程对象
     * @return courseCatalog
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    public CourseCatalog saveCourseCatalog(CourseCatalog courseCatalog) {
        if (DataUtil.idIsNotNull(courseCatalog.getId())) {//修改
            CourseCatalog _courseCatalog = this.findById(courseCatalog.getId());
            _courseCatalog.setCatalogName(courseCatalog.getCatalogName());
            _courseCatalog.setMaterialTypeKey(courseCatalog.getMaterialTypeKey());
            _courseCatalog.setMaterialId(courseCatalog.getMaterialId());
            _courseCatalog.setLessonTime(courseCatalog.getLessonTime());
            _courseCatalog.setLessonStartTime(courseCatalog.getLessonStartTime());
            _courseCatalog.setLessonEndTime(courseCatalog.getLessonEndTime());
            _courseCatalog.setReplay(courseCatalog.getReplay());
            _courseCatalog.setLiveId(courseCatalog.getLiveId());
            _courseCatalog.setVideoDuration(courseCatalog.getVideoDuration());
            _courseCatalog.setPlaybackId(courseCatalog.getPlaybackId());
            if (StringUtils.isNotEmpty(courseCatalog.getBackCode())) {
                _courseCatalog.setBackCode(courseCatalog.getBackCode());
            } else {
                _courseCatalog.setBackCode(" ");
            }
            _courseCatalog.setAudition(courseCatalog.getAudition());
            _courseCatalog.setAuditionTime(courseCatalog.getAuditionTime());
            _courseCatalog.setLorePointIds(courseCatalog.getLorePointIds());
            _courseCatalog.setPractice(courseCatalog.getPractice());
            if (StringUtils.isNotEmpty(_courseCatalog.getDatums()) && StringUtils.isEmpty(courseCatalog.getDatums())) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("id", _courseCatalog.getId());
                map.put("columnName", "datums");
                courseCatalogDao.updateColumnNull(CourseCatalog.class, map);
            }
            _courseCatalog.setDatums(courseCatalog.getDatums());
            _courseCatalog.setQuestionIds(courseCatalog.getQuestionIds());
            this.updateById(_courseCatalog, null);
            this.updateCourseService(courseCatalog, 2);
            ArrayList<CourseCatalog> courseCatalogs = new ArrayList<>();
            courseCatalogs.add(courseCatalog);
            this.updateCourseTeacher(courseCatalogs, courseCatalog.getCourseId(), 1);
            //修改课程节点数量、类型
            this.setCourseNodeNumOrContainNodeType(courseCatalog.getCourseId());
        } else {//添加
            this.save(courseCatalog);
            this.updateCourseService(courseCatalog, 1);
            ArrayList<CourseCatalog> courseCatalogs = new ArrayList<>();
            courseCatalogs.add(courseCatalog);
            this.updateCourseTeacher(courseCatalogs, courseCatalog.getCourseId(), 1);
            //修改课程节点数量、类型
            this.setCourseNodeNumOrContainNodeType(courseCatalog.getCourseId());
        }

        return courseCatalog;
    }

    /**
     * 保存课程导入的模块数据
     *
     * @param courseId     课程ID
     * @param couMouldList 模块列表，包含素材数据
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> saveCourseCatalogByMould(BigDecimal courseId, List<CouMould> couMouldList) {
        if (ObjectUtils.isNotEmpty(couMouldList)) {
            //获取课程目录计算排序
            BigDecimal count = this.count(" courseId = " + courseId);
            List<CourseCatalog> parentCourseCatalogList = new ArrayList<>();
            Date currentTime = new Date();
            AtomicInteger index = new AtomicInteger(count.intValue());
            couMouldList.parallelStream().forEach(couMould -> {
                //父级目录
                CourseCatalog parentCatalog = new CourseCatalog();
                parentCatalog.setCourseId(courseId);//设置课程ID
                parentCatalog.setCatalogName(couMould.getMouldName());
                parentCatalog.setNodeType(1);//设置为章类型
                parentCatalog.setMaterialId(new BigDecimal(0));
                parentCatalog.setMouldId(couMould.getId());//设置模块ID
                parentCatalog.setParentId(new BigDecimal(0));//不能是空，如果空子级的父ID添加不成功
                parentCatalog.setLessonStartTime(currentTime);//不能是空，如果是空子级是直播素材类型的目录就添加不了时间
                parentCatalog.setLessonEndTime(currentTime);
                parentCatalog.setSort(index.incrementAndGet());
                parentCourseCatalogList.add(parentCatalog);
                //获取模块关联的素材数据列表
                List<CouMouldMaterial> mouldMaterials = couMould.getCouMouldMaterialList();
                List<CourseCatalog> childList = new ArrayList<>();
                if (ObjectUtils.isNotEmpty(mouldMaterials)) {
                    mouldMaterials.forEach(couMouldMaterial -> {
                        if (ObjectUtils.isNotEmpty(couMouldMaterial.getCouMaterial())) {
                            //得到素材
                            CouMaterial material = couMouldMaterial.getCouMaterial();
                            //子级目录
                            CourseCatalog childCatalog = new CourseCatalog();
                            childCatalog.setCourseId(courseId);//设置课程ID
                            childCatalog.setCatalogName(material.getName());
                            childCatalog.setNodeType(2);//设置为节类型
                            childCatalog.setMaterialId(material.getId());
                            childCatalog.setMouldId(couMould.getId());//设置模块ID
                            childCatalog.setParentId(parentCatalog.getId());
                            childCatalog.setMaterialTypeKey(material.getTypeKey());
                            if (material.getTypeKey().equals(MaterialType.TYPE_KEY_LIVE.getKey())) {//如果是直播素材，则设置直播时间
                                childCatalog.setLessonStartTime(material.getLiveBeginTime());
                                childCatalog.setLessonEndTime(material.getLiveEndTime());
                            }
                            childList.add(childCatalog);
                        }
                    });
                }
                parentCatalog.setChildCourseCatalogList(childList);
            });
            if (ObjectUtils.isNotEmpty(parentCourseCatalogList)) {
                //保存父级
                this.batchSave(parentCourseCatalogList);
                List<CourseCatalog> childList = new ArrayList<>();
                parentCourseCatalogList.parallelStream().forEach(parent -> {
                    List<CourseCatalog> _childList = parent.getChildCourseCatalogList();
                    if (ObjectUtils.isNotEmpty(_childList)) {
                        _childList.parallelStream().forEach(child -> {
                            child.setParentId(parent.getId());
                            child.setSort(index.incrementAndGet());
                        });
                    }
                    childList.addAll(_childList);
                });
                //保存子级
                if (ObjectUtils.isNotEmpty(childList)) {
                    this.batchSave(childList);
                    this.updateCourseTeacher(childList, courseId, 1);
                }
                //修改课程节点数量、类型
                this.setCourseNodeNumOrContainNodeType(parentCourseCatalogList.get(0).getCourseId());
                List<CourseCatalog> allChildList = new ArrayList<>();
                parentCourseCatalogList.forEach(parent -> {
                    List<CourseCatalog> _childList = parent.getChildCourseCatalogList();
                    if (ObjectUtils.isNotEmpty(_childList)) {
                        parent.setChildCourseCatalogList(null);
                        allChildList.addAll(_childList);
                    }
                });
                if (ObjectUtils.isNotEmpty(allChildList)) {
                    parentCourseCatalogList.addAll(allChildList);
                }
                return parentCourseCatalogList;
            }
        }
        return null;
    }

    /**
     * 当模块有添加素材，同时生成课程关联模块的目录
     *
     * @param couMouldMaterialList 数据列表
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    public void saveMouldMaterialData(List<CouMouldMaterial> couMouldMaterialList) {
        if (ObjectUtils.isNotEmpty(couMouldMaterialList)) {
            //模块ID
            BigDecimal mouldId = couMouldMaterialList.get(0).getMouldId();
            CourseCatalogCondition condition = new CourseCatalogCondition();
            condition.setMouldId(mouldId);
            condition.setNotParentId(true);//父级ID不为空的
            //获取之前有关联该模块的目录数据
            List<CourseCatalog> courseCatalogs = this.findCourseCatalogList(condition, false, false, false, false);
            if (ObjectUtils.isNotEmpty(courseCatalogs)) {
                String materialIds = couMouldMaterialList.stream().map(e -> e.getMaterialId().toString()).collect(Collectors.joining(","));
                Map<BigDecimal, CouMaterial> couMaterialMaps = couMaterialBiz.findMaterialByIdsToMap(materialIds, false, false);
                couMouldMaterialList.forEach(e -> {
                    CouMaterial material = couMaterialMaps.get(e.getMaterialId());
                    e.setCouMaterial(material);
                });
                List<CourseCatalog> courseCatalogList = new ArrayList<>();
                //生成课程个数
                courseCatalogs.forEach(e -> {
                    //生成的目录个数
                    couMouldMaterialList.forEach(em -> {
                        CourseCatalog catalog = new CourseCatalog();
                        catalog.setCourseId(e.getCourseId());//设置课程ID
                        catalog.setMaterialId(em.getMaterialId());//设置素材ID
                        catalog.setMouldId(mouldId);//设置模块ID
                        catalog.setNodeType(2);//设置成节类型
                        catalog.setCatalogName(em.getCouMaterial().getName());//设置目录的名
                        catalog.setMaterialTypeKey(em.getCouMaterial().getTypeKey());//设置类型
                        catalog.setParentId(e.getId());//设置父级ID
                        catalog.setMaterialTypeKey(em.getCouMaterial().getTypeKey());//设置目录类型（直播、文章、视频、音频）
                        if (MaterialType.TYPE_KEY_LIVE.getKey().equals(em.getCouMaterial().getTypeKey())) {//如果是直播类型的素材
                            catalog.setLessonStartTime(em.getCouMaterial().getLiveBeginTime());//设置直播开始时间
                            catalog.setLessonEndTime(em.getCouMaterial().getLiveEndTime());//设置直播的结束时间
                        }
                        catalog.setAudition(1);//设置试听状态为不可以试听
                        courseCatalogList.add(catalog);
                    });
                });
                //保存目录信息
                if (ObjectUtils.isNotEmpty(courseCatalogList)) {
                    this.batchSave(courseCatalogList);
                    String courseIds = courseCatalogList.stream().map(e -> e.getCourseId().toString()).distinct().collect(Collectors.joining(","));
                    Map<BigDecimal, Course> courseMaps = courseBiz.findCourseToMapByIds(courseIds, false, false, false);
                    Map<BigDecimal, List<CourseCatalog>> courseCatalogListMap = courseCatalogList.stream().collect(Collectors.groupingBy(e -> e.getCourseId()));
                    List<Course> courseList = new ArrayList<>();
                    courseCatalogListMap.forEach((k, v) -> {
                        Course _course = courseMaps.get(k);
                        if (ObjectUtils.isNotEmpty(_course) && ObjectUtils.isNotEmpty(v)) {
                            courseList.add(_course);
                        }
                    });
                    //进行批量更新
                    if (ObjectUtils.isNotEmpty(courseList)) {
                        //设置课程节点的类型、节点数量
                        this.setCourseNodeNumOrContainNodeType(courseList);
                    }
                }
            }
        }
    }

    /**
     * 删除目录数据
     *
     * @param ids 目录ID串
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    public void deleteCourseCatalogByIds(String ids) {
        List<CourseCatalog> courseCatalogs = this.find(" id in (" + ids + ") or parentId in (" + ids + ")", null, null);
        if (ObjectUtils.isNotEmpty(courseCatalogs)) {
            BigDecimal courseId = courseCatalogs.get(0).getCourseId();
            String mouldIds = courseCatalogs.stream().filter(e -> DataUtil.idIsNotNull(e.getMouldId())).map(e -> e.getMouldId().toString()).collect(Collectors.joining(","));
            this.updateCourseCatalogMouldId(courseId, mouldIds);
            this.deleteWhereSql("id in (" + ids + ") or parentId in (" + ids + ")");
            //设置课程节点的类型、节点数量
            this.setCourseNodeNumOrContainNodeType(courseId);
            //修改课程关联教师
            this.updateCourseTeacher(courseCatalogs, courseId, 2);
            CourseCatalog courseCatalog = new CourseCatalog();
            courseCatalog.setCourseId(courseId);
            courseCatalog.setNodeType(2);
            this.updateCourseService(courseCatalog, 3);
        }
    }

    /**
     * 当模块有删除素材，同时删除课程关联模块的目录
     *
     * @param couMouldMaterialList 数据列表
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    public void deleteMouldMaterialData(List<CouMouldMaterial> couMouldMaterialList) {
        if (ObjectUtils.isNotEmpty(couMouldMaterialList)) {
            BigDecimal mouldId = couMouldMaterialList.get(0).getMouldId();
            List<CourseCatalog> courseCatalogList = this.find(" mouldId = " + mouldId, null, null);
            String courseIds = courseCatalogList.stream().map(e -> e.getCourseId().toString()).distinct().collect(Collectors.joining(","));
            String materialIds = couMouldMaterialList.stream().map(e -> e.getMaterialId().toString()).distinct().collect(Collectors.joining(","));
            //删除模块对应课程的目录信息
            if (StringUtils.isNotEmpty(courseIds)) {
                this.deleteWhereSql("courseId in (" + courseIds + ") and mouldId=" + mouldId + " and materialId in (" + materialIds + ")");
                Map<BigDecimal, Course> courseMaps = courseBiz.findCourseToMapByIds(courseIds, false, false, false);

                List<Course> courseList = new ArrayList<>();
                courseMaps.forEach((k, v) -> {
                    Course _course = courseMaps.get(k);
                    if (ObjectUtils.isNotEmpty(_course) && ObjectUtils.isNotEmpty(v)) {
                        courseList.add(_course);
                    }
                });
                //进行批量更新
                if (ObjectUtils.isNotEmpty(courseList)) {
                    //设置课程节点的类型、节点数量
                    this.setCourseNodeNumOrContainNodeType(courseList);
                }
            }
        }
    }

    /**
     * 修改章节父级ID
     *
     * @param id
     * @param parentId
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    public void updateCourseCatalogParent(BigDecimal id, BigDecimal parentId) {
        CourseCatalog courseCatalog = this.findCourseCatalogById(id, false, false, false, false);
        CourseCatalog parentCourseCatalog = this.findCourseCatalogById(parentId, false, false, false, false);
        if (ObjectUtils.isNotEmpty(courseCatalog) && ObjectUtils.isNotEmpty(parentCourseCatalog)) {
            //如果原来有模块ID，且新父级的模块ID不原来的模块ID一致时，
            if (DataUtil.idIsNotNull(courseCatalog.getMouldId())) {
                String mouldIds = courseCatalog.getMouldId().toString();
                if (DataUtil.idIsNotNull(parentCourseCatalog.getMouldId())) {
                    mouldIds += "," + parentCourseCatalog.getMouldId().toString();
                }
                //设置模块ID当前之前归属的模块和父级
                this.updateCourseCatalogMouldId(courseCatalog.getCourseId(), mouldIds);
                courseCatalog.setMouldId(new BigDecimal(0));
            }
            //设置新的父级ID
            courseCatalog.setParentId(parentId);
            //执行更新操作
            this.updateById(courseCatalog, null);
        }
    }

    /**
     * 通过课程ID，查询课程的目录数据列表,并且分层
     *
     * @param buyCourseId     购买课程的ID
     * @param userId          用户ID
     * @param courseId        需要查询目录的课程ID
     * @param setMaterialData 是否设置素材数据
     * @param setLoresetPoint 设置知识点
     * @param setQuestion     设置试题
     * @param group           按题型分组
     * @param setPlayRecord   设置播放记录
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> findCourseCatalogLayeredByCourseId(BigDecimal buyCourseId,
                                                                  BigDecimal userId,
                                                                  BigDecimal courseId,
                                                                  boolean setMaterialData,
                                                                  boolean setLoresetPoint, boolean setQuestion, boolean group, boolean setPlayRecord) {
        List<CourseCatalog> courseCatalogList = this.findCourseCatalogByCourseId(courseId, setMaterialData, setLoresetPoint, setQuestion, group);
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            //获取素材的讲师是否为问答讲师
            String teacherIds = courseCatalogList.stream().filter(e -> ObjectUtils.isNotEmpty(e.getMaterial())).map(e -> e.getMaterial().getTeacherId().toString()).collect(Collectors.joining(","));
            Map<BigDecimal, Map<String, Object>> teacherMaps = sysTeacherService.findSysTeacherToMapByIds(teacherIds, false, false, false, false, false);
            courseCatalogList.forEach(e -> {
                CouMaterial material = e.getMaterial();
                if (ObjectUtils.isNotEmpty(material)) {
                    material.setPlayUrl(null);
                    material.setArticleSummary(null);
                    material.setArticleContext(null);
                    if (ObjectUtils.isNotEmpty(teacherMaps)) {
                        Map<String, Object> teacherMap = teacherMaps.get(material.getTeacherId());
                        if (ObjectUtils.isNotEmpty(teacherMap) && Integer.valueOf(teacherMap.get("isQuestion").toString()) == 1) {
                            material.setTeacherQuestion(true);
                        }
                    }
                }
            });
        }
        //设置播放记录
        setPlayRecord(courseCatalogList, buyCourseId, courseId, userId, setPlayRecord);
        return this.handleLayered(courseCatalogList);
    }

    /**
     * 通过课程ID，查询课程的目录数据列表
     *
     * @param courseId        设置ID
     * @param setMaterialData 是否设置素材数据
     * @param setLoresetPoint 设置知识点
     * @param setQuestion     设置试题
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> findCourseCatalogByCourseId(BigDecimal courseId, boolean setMaterialData,
                                                           boolean setLoresetPoint, boolean setQuestion, boolean group) {
        CourseCatalogCondition condition = new CourseCatalogCondition();
        condition.setCourseId(courseId);
        List<CourseCatalog> courseCatalogs = this.findCourseCatalogList(condition, setMaterialData, setLoresetPoint, setQuestion, group);
        return courseCatalogs;
    }

    /**
     * 通过ID查询目录数据
     *
     * @param id              ID
     * @param setMaterialData 是否设置素材数据
     * @param setLoresetPoint 设置知识点
     * @param setQuestion     设置试题
     * @return CourseCatalog
     */
    public CourseCatalog findCourseCatalogById(BigDecimal id, boolean setMaterialData, boolean setLoresetPoint, boolean setQuestion, boolean group) {
        List<CourseCatalog> courseCatalogList = this.findCourseCatalogByIds(id.toString(), setMaterialData, setLoresetPoint, setQuestion, group);
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            return courseCatalogList.get(0);
        }
        return null;
    }

    /**
     * 通过ID串，查询目录数据
     *
     * @param ids             目录ID串
     * @param setMaterialData 是否设置素材数据
     * @param setLoresetPoint 设置知识点
     * @param setQuestion     设置试题
     * @return Map<BigDecimal                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               CourseCatalog>
     */
    public Map<BigDecimal, CourseCatalog> findCourseCatalogMapByIds(String ids, boolean setMaterialData,
                                                                    boolean setLoresetPoint, boolean setQuestion, boolean group) {
        List<CourseCatalog> courseCatalogList = findCourseCatalogByIds(ids, setMaterialData, setLoresetPoint, setQuestion, group);
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            return courseCatalogList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
        }
        return null;
    }

    /**
     * 通过ID串，查询目录数据
     *
     * @param ids             目录ID串
     * @param setMaterialData 是否设置素材数据
     * @param setLoresetPoint 设置知识点
     * @param setQuestion     设置试题
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> findCourseCatalogByIds(String ids, boolean setMaterialData,
                                                      boolean setLoresetPoint, boolean setQuestion, boolean group) {
        CourseCatalogCondition condition = new CourseCatalogCondition();
        condition.setQueryIds(ids);
        return this.findCourseCatalogList(condition, setMaterialData, setLoresetPoint, setQuestion, group);
    }

    /**
     * 多条件查询目录数据
     *
     * @param condition       查询条件对象
     * @param setMaterialData 是否设置素材数据
     * @param setLoresetPoint 设置知识点
     * @param setQuestion     设置试题
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> findCourseCatalogList(CourseCatalogCondition condition, boolean setMaterialData,
                                                     boolean setLoresetPoint, boolean setQuestion, boolean group) {
        List<CourseCatalog> courseCatalogs = this.find(this.getWhereSql(condition), condition.getCount(), null);
        this.setMaterialData(courseCatalogs, setMaterialData);
        this.setLiveCatalogPlayStatus(courseCatalogs);
        this.setLoresetPointData(courseCatalogs, setLoresetPoint);
        this.setCourseCatalogQuestion(courseCatalogs, setQuestion, group);
        return courseCatalogs;
    }

    /**
     * 验证目录选择的素材是否重复
     *
     * @param courseId   课程ID
     * @param materialId 素材ID
     * @return true重复，false不重复
     */
    public boolean checkRepeatMaterial(BigDecimal courseId, BigDecimal materialId, BigDecimal id) {
        if (DataUtil.idIsNotNull(materialId)) {
            CourseCatalog catalog = null;
            if (DataUtil.idIsNotNull(id)) {
                catalog = this.findOne("courseId=" + courseId + " and materialId=" + materialId + " and id =" + id, null);
                if (catalog != null) {
                    return false;
                }
            } else {
                catalog = this.findOne("courseId=" + courseId + " and materialId=" + materialId, null);
            }
            if (catalog != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 验证目录选择的素材是否重复
     *
     * @param courseId 课程ID
     * @param mouldIds 模块ID串
     * @return 重复信息
     */
    public String checkRepeatMould(BigDecimal courseId, String mouldIds) {
        if (StringUtils.isNotEmpty(mouldIds) && DataUtil.idIsNotNull(courseId)) {
            List<CourseCatalog> catalogList = this.find("courseId=" + courseId + " and mouldId in(" + mouldIds + ")", null, null);
            if (ObjectUtils.isNotEmpty(catalogList)) {
                String _mouldIds = catalogList.stream().map(e -> e.getMouldId().toString()).collect(Collectors.joining(","));
                List<CouMould> couMouldList = couMouldBiz.findCouMouldByIds(_mouldIds, false, false, false);
                if (ObjectUtils.isNotEmpty(couMouldList)) {
                    return "模块【" + couMouldList.stream().map(e -> e.getMouldName()).collect(Collectors.joining(",")) + "】已添加过";
                }
            }
        }
        return null;
    }

    /**
     * 设置直播课程节点
     *
     * @param course                 课程对象
     * @param setLiveCourseNodesData 是否设置数据
     */
    public void setLiveCourseNodesData(Course course, boolean setLiveCourseNodesData) {
        if (setLiveCourseNodesData && ObjectUtils.isNotEmpty(course)) {
            List<Course> courseList = new ArrayList<>();
            courseList.add(course);
            setLiveCourseNodesData(courseList, true);
        }
    }

    /**
     * 设置直播课程节点
     *
     * @param courseList             课程列表
     * @param setLiveCourseNodesData 是否设置数据
     */
    public void setLiveCourseNodesData(List<Course> courseList, boolean setLiveCourseNodesData) {
        if (ObjectUtils.isNotEmpty(courseList) && setLiveCourseNodesData) {
            String courseIds = courseList.stream().map(e -> e.getId().toString()).collect(Collectors.joining(","));
            Map<BigDecimal, CourseCatalog> courseCatalogMap = this.findLiveCourseListNodeMap(courseIds);
            if (ObjectUtils.isNotEmpty(courseCatalogMap)) {
                courseList.forEach(course -> {
                    CourseCatalog courseCatalog = courseCatalogMap.get(course.getId());
                    course.setLiveCourseCatalog(courseCatalog);
                    if (ObjectUtils.isNotEmpty(courseCatalog)) {
                        ArrayList<CourseCatalog> courseCatalogs = new ArrayList<>();
                        courseCatalogs.add(courseCatalog);
                        this.setMaterialData(courseCatalogs, true);
                        this.setLiveCatalogPlayStatus(courseCatalogs);
                    }
                });
            }
        }
    }

    /**
     * 通过课程ID，查询课程的目录数据列表
     *
     * @param courseId 设置ID
     * @return List<CourseCatalog>
     */
    public List<CourseCatalog> findCourseCatalogPracticeByCourseId(BigDecimal courseId, double courseScoreRate) {
        CourseCatalogCondition condition = new CourseCatalogCondition();
        condition.setCourseId(courseId);
        List<CourseCatalog> courseCatalogs = this.findCourseCatalogList(condition, false, false, false, false);
        for (CourseCatalog courseCatalog : courseCatalogs) {
            HashMap<Object, Object> param = new HashMap<>();
            param.put("courseId", courseCatalog.getCourseId());
            param.put("catalogId", courseCatalog.getId());
            param.put("courseScoreRate", courseScoreRate);
            Map map = examRecordService.queryPracticePassNumber(param);
            if (ObjectUtils.isNotEmpty(map.get("passNumber"))) {
                courseCatalog.setPracticePassNumber(Integer.valueOf(map.get("passNumber").toString()));
            } else {
                courseCatalog.setPracticePassNumber(0);
            }
            if (ObjectUtils.isNotEmpty(map.get("headcount"))) {
                courseCatalog.setPracticeHeadcount(Integer.valueOf(map.get("headcount").toString()));
            } else {
                courseCatalog.setPracticeHeadcount(0);
            }
        }
        return courseCatalogs;
    }

    /**
     * 查询可要提醒的直播目录节点(开始直播前30分钟)
     *
     * @return List<CourseLiveReminder>
     */
    public List<CourseLiveReminder> findCourseLiveReminderList() {
        Map<String, String> params = new HashMap<>();
        Date currentTime = new Date();
        Date endTime = DateUtils.addMinutes(currentTime, 30);
        params.put("startTime", DateUtils.format(currentTime, "yyyy-MM-dd HH:mm:ss"));
        params.put("endTime", DateUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
        List<CourseLiveReminder> courseLiveReminderList = courseCatalogDao.findCourseLiveReminderList(CourseCatalog.class, params);
        if (ObjectUtils.isNotEmpty(courseLiveReminderList)) {
            Set<BigDecimal> courseIdSet = new HashSet<>();
            courseLiveReminderList.forEach(e -> {
                if (DataUtil.idIsNotNull(e.getPackageId())) {
                    courseIdSet.add(e.getPackageId());
                }
                courseIdSet.add(e.getCourseId());
            });
            String courseIds = courseIdSet.stream().map(e -> e.toString()).collect(Collectors.joining(","));
            Map<BigDecimal, Course> courseMap = courseBiz.findCourseToMapByIds(courseIds, false, false, false, false);
            courseLiveReminderList.forEach(e -> {
                e.setPackageCourse(courseMap.get(e.getPackageId()));
                e.setCourse(courseMap.get(e.getCourseId()));
            });
        }
        return courseLiveReminderList;
    }

    //================================================

    /**
     * 设置播放记录
     *
     * @param courseCatalogList 课程目录列表
     * @param courseId          课程ID（购买的课程ID）
     * @param courseId          课程ID（套餐下的课程）
     * @param userId            用户ID
     * @param setPlayRecord     是否设置播放记录
     * @return List<CourseCatalog>
     */
    private List<CourseCatalog> setPlayRecord(List<CourseCatalog> courseCatalogList, BigDecimal buyCourseId, BigDecimal courseId, BigDecimal userId, boolean setPlayRecord) {
        if (ObjectUtils.isNotEmpty(courseCatalogList)
                && DataUtil.idIsNotNull(courseId)
                && DataUtil.idIsNotNull(userId) && setPlayRecord) {
            String catalogIds = courseCatalogList.stream().map(e -> e.getId().toString()).collect(Collectors.joining(","));
            List<CoursePlayRecord> coursePlayRecordList = coursePlayRecordBiz.find(" catalogId in (" + catalogIds + ") and buyCourseId= " + buyCourseId + " and courseId=" + courseId + " and userId=" + userId, null, null);
            Map<BigDecimal, CourseCatalog> courseCatalogMap = courseCatalogList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
            if (ObjectUtils.isNotEmpty(coursePlayRecordList)) {
                coursePlayRecordList.forEach(playRecord -> {
                    CourseCatalog catalog = courseCatalogMap.get(playRecord.getCatalogId());
                    if (ObjectUtils.isNotEmpty(catalog)) {
                        if (playRecord.getFinish().intValue() == 2) {
                            catalog.setProgress("100%");
                        } else {
                            Integer duration = 0;
                            if ("ARTICLE".equals(catalog.getMaterialTypeKey())) { //文字计算总时长
                                duration = playRecord.getDurationCatalogNum();
                            } else {
                                duration = playRecord.getMaxDuration();
                            }
                            Integer videoDuration = catalog.getVideoDuration();
                            if (ObjectUtils.isNotEmpty(duration) && ObjectUtils.isNotEmpty(videoDuration)) {
                                BigDecimal max = new BigDecimal(100);
                                //计算学习进度
                                BigDecimal studySpeed = AmountUtils.safeDivide(duration, videoDuration, 1).multiply(new BigDecimal("100"));
                                if (studySpeed.compareTo(max) == 1) {
                                    catalog.setProgress("100%");
                                    playRecord.setFinish(2);
                                } else {
                                    catalog.setProgress(studySpeed.toString() + "%");
                                }
                            }else{
                                catalog.setProgress("0%");
                            }
                        }
                        catalog.setCoursePlayRecord(playRecord);
                    }
                });
            }
        }
        return courseCatalogList;
    }

    /**
     * 处理分层
     *
     * @param courseCatalogList
     * @return List<CourseCatalog>
     */
    private List<CourseCatalog> handleLayered(List<CourseCatalog> courseCatalogList) {
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            Map<BigDecimal, List<CourseCatalog>> courseCatalogListMap = courseCatalogList.stream().collect(Collectors.groupingBy(e -> e.getParentId()));
            List<CourseCatalog> parentList = courseCatalogListMap.get(new BigDecimal(0));//得到父级
            if (ObjectUtils.isNotEmpty(parentList)) {
                parentList.forEach(e -> {
                    List<CourseCatalog> childList = courseCatalogListMap.get(e.getId());
                    e.setChildCourseCatalogList(childList);
                });
            }
            return parentList;
        }
        return null;
    }

    /**
     * 设置课程的包含的素材类型、和素材数量
     *
     * @param courseId 课程ID
     */
    private void setCourseNodeNumOrContainNodeType(BigDecimal courseId) {
        Course course = courseBiz.findById(courseId);
        this.setCourseNodeNumOrContainNodeType(course);
    }

    /**
     * 设置课程的包含的素材类型、和素材数量
     *
     * @param course 课程对象
     */
    private void setCourseNodeNumOrContainNodeType(Course course) {
        if (ObjectUtils.isNotEmpty(course)) {
            this.setCourseNodeNumOrContainNodeType(Collections.singletonList(course));
        }
    }

    /**
     * 设置课程的包含的素材类型、和素材数量
     *
     * @param courseList 课程列表
     */
    private void setCourseNodeNumOrContainNodeType(List<Course> courseList) {
        if (ObjectUtils.isNotEmpty(courseList)) {
            String courseIds = courseList.stream().map(e -> e.getId().toString()).distinct().collect(Collectors.joining(","));
            List<CourseCatalog> courseCatalogList = this.find(" courseId in (" + courseIds + ") and nodeType =2", null, null);
            if (ObjectUtils.isNotEmpty(courseCatalogList)) {
                Map<BigDecimal, List<CourseCatalog>> courseCatalogListMap = courseCatalogList.stream().collect(Collectors.groupingBy(e -> e.getCourseId()));
                List<Course> _courseList = new ArrayList<>();
                courseList.forEach(course -> {
                    int nodeNum = 0;
                    Set<String> typeSet = new HashSet<>();
                    String containNodeType = "";
                    //课程的目录
                    List<CourseCatalog> courseCatalogs = courseCatalogListMap.get(course.getId());
                    if (ObjectUtils.isNotEmpty(courseCatalogs)) {
                        //设置节点数量
                        nodeNum = courseCatalogs.size();
                        //设置包含的节点类型
                        courseCatalogs.stream().filter(e -> StringUtils.isNotEmpty(e.getMaterialTypeKey())).forEach(e -> typeSet.add(MaterialType.getValues(e.getMaterialTypeKey())));
                    }
                    if (ObjectUtils.isNotEmpty(typeSet)) {
                        containNodeType = typeSet.stream().collect(Collectors.joining("、"));
                    }
                    Course _course = new Course();
                    _course.setId(course.getId());
                    _course.setNodeNum(nodeNum);
                    _course.setContainNodeType(containNodeType);
                    _courseList.add(_course);
                });
                if (ObjectUtils.isNotEmpty(_courseList)) {
                    courseBiz.updateBatch(_courseList);
                }
            }else{

                List<Course> _courseList = new ArrayList<>();
                courseList.forEach(course -> {
                    Course _course = new Course();
                    _course.setId(course.getId());
                    _course.setNodeNum(0);
                    _course.setContainNodeType("");
                    _courseList.add(_course);

                });
                if (ObjectUtils.isNotEmpty(_courseList)) {
                    courseBiz.updateBatch(_courseList);
                }

            }
        }
    }

    /**
     * 修改章节的模块ID为0
     *
     * @param courseId 课程ID
     * @param mouldIds 模块ID串
     */
    private void updateCourseCatalogMouldId(BigDecimal courseId, String mouldIds) {
        if (StringUtils.isNotEmpty(mouldIds) && DataUtil.idIsNotNull(courseId)) {
            CourseCatalog catalog = new CourseCatalog();
            catalog.setMouldId(new BigDecimal(0));
            this.updateByWhereSql(catalog, " courseId = " + courseId + " and mouldId in (" + mouldIds + ")");
        }
    }

    /**
     * 设置试题数据
     *
     * @param courseCatalogList 章节
     * @param setQuestion       设置试题
     */
    private void setCourseCatalogQuestion(List<CourseCatalog> courseCatalogList, boolean setQuestion, boolean group) {
        if (setQuestion && ObjectUtils.isNotEmpty(courseCatalogList)) {
            String questionIds = DataUtil.joining(courseCatalogList, CourseCatalog::getQuestionIds);
            questionIds = StringUtils.subHeadTailString(questionIds, ",");
            if (StringUtils.isNotEmpty(questionIds)) {
                Map<String, Object> condition = new HashMap<>();
                condition.put("ids", StringUtils.subHeadTailString(questionIds, ","));
                condition.put("format", true);
                Map<BigDecimal, Map<String, Object>> questionMap = examQuestionsService.findExamQuestionByIds(condition);
                if (ObjectUtils.isNotEmpty(questionMap)) {
                    courseCatalogList.forEach((v) -> {
                        String _questionIds = StringUtils.subHeadTailString(v.getQuestionIds(), ",");
                        List<Map<String, Object>> questionList = new ArrayList<>();
                        if (StringUtils.isNotEmpty(_questionIds)) {
                            Arrays.stream(_questionIds.split(",")).forEach(id -> {
                                Map<String, Object> question = questionMap.get(new BigDecimal(id));
                                if (ObjectUtils.isNotEmpty(question)) {
                                    questionList.add(question);
                                }
                            });
                        }
                        v.setQuestionList(questionList);
                    });
                }
            }
        }
    }

    /**
     * 设置知识点数据
     *
     * @param courseCatalogList 章节
     * @param setLoresetPoint   设置知识点
     */
    private void setLoresetPointData(List<CourseCatalog> courseCatalogList, boolean setLoresetPoint) {
        if (ObjectUtils.isNotEmpty(courseCatalogList) && setLoresetPoint) {
            List<String[]> loresetData = this.getLoresetData(courseCatalogList);
            if (ObjectUtils.isEmpty(loresetData)) {
                return;
            }
            // 知识体系
            Map<String, Map<String, Object>> loreset = this.getLoreset(loresetData);
            // 知识点
            Map<String, Map<String, Object>> loresetPoint = this.getLoresetPoint(loresetData);
            Map<String, Object> emptyMap = Collections.emptyMap();
            courseCatalogList.forEach((v) -> {
                if (StringUtils.isNotEmpty(v.getLorePointIds())) {
                    String[] arrays = v.getLorePointIds().split("#");
                    Map<String, String> loresetMapData = new HashMap<>();
                    for (String s : arrays) {
                        s = StringUtils.subHeadTailString(s, ",");
                        String[] array = s.split(",");
                        StringJoiner names = new StringJoiner(" > ");
                        names.add(loreset.getOrDefault(array[0], emptyMap).getOrDefault("loresetName", "").toString());
                        names.add(loresetPoint.getOrDefault(array[1], emptyMap).getOrDefault("pointName", "").toString());
                        if (array.length == 3) {
                            names.add(loresetPoint.getOrDefault(array[2], emptyMap).getOrDefault("pointName", "").toString());
                        }
                        loresetMapData.put(s, names.toString());
                    }
                    v.setLoresetDataMap(loresetMapData);
                }
            });
        }
    }

    /**
     * 获得知识体系数据
     *
     * @param loresetData 知识体系、考点id数据
     * @return 知识体系
     */
    private Map<String, Map<String, Object>> getLoreset(List<String[]> loresetData) {
        String loresetIds = loresetData.stream().map((v) -> v[0]).collect(Collectors.joining(","));
        loresetIds = DataUtil.filterNotNumberStr(loresetIds);
        Map<BigDecimal, Map<String, Object>> loresetMap = loresetService.findLorestListByIdsToMap(loresetIds, false, false, false);
        Map<String, Map<String, Object>> loresetMapCopy = new HashMap<>();
        loresetMap.forEach((k, v) -> loresetMapCopy.put(k.toString(), v));
        return loresetMapCopy;
    }

    /**
     * 获得知识体系、考点id数据(知识体系id和考点id组成的数组)
     * 例如某试题的考点数据为 ,1,2,3,#,1,2,4,
     * 则返回的数据为[[1,2,3],[1,2,4]]
     *
     * @param courseCatalogList 章节
     * @return 知识体系、考点id数据
     */
    private List<String[]> getLoresetData(List<CourseCatalog> courseCatalogList) {
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            return courseCatalogList.stream()
                    .map(CourseCatalog::getLorePointIds)
                    .filter(StringUtils::isNotEmpty)
                    .flatMap((v) -> Stream.of(v.split("#")))
                    .map((v) -> StringUtils.subHeadTailString(v, ","))
                    .map((v) -> v.split(","))
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 获得考点数据
     *
     * @param loresetData 知识体系、考点id数据
     * @return 考点
     * @see #getLoresetData(List)
     */
    private Map<String, Map<String, Object>> getLoresetPoint(List<String[]> loresetData) {
        String loresetIds = loresetData.stream().flatMap((v) -> Stream.of(Arrays.copyOfRange(v, 1, v.length))).collect(Collectors.joining(","));
        Map<BigDecimal, Map<String, Object>> loresetPointMap = loresetPointService.findLoresetPointByIdsToMap(loresetIds, false);
        Map<String, Map<String, Object>> loresetPointMapCopy = new HashMap<>();
        loresetPointMap.forEach((k, v) -> loresetPointMapCopy.put(k.toString(), v));
        return loresetPointMapCopy;
    }

    /**
     * 设置课程目录的素材数据
     *
     * @param courseCatalogList
     * @param setMaterialData
     * @return List<CourseCatalog>
     */
    public  List<CourseCatalog> setMaterialData(List<CourseCatalog> courseCatalogList, boolean setMaterialData) {
        if (ObjectUtils.isNotEmpty(courseCatalogList) && setMaterialData) {
            String materialIds = courseCatalogList.stream().filter(e -> DataUtil.idIsNotNull(e.getMaterialId())).map(e -> e.getMaterialId().toString()).collect(Collectors.joining(","));
            if (StringUtils.isNotEmpty(materialIds)) {
                List<CouMaterial> materialList = couMaterialBiz.findMaterialByIds(materialIds, false, false);
                if (ObjectUtils.isNotEmpty(materialList)) {
                    Map<BigDecimal, CouMaterial> materialMaps = materialList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
                    courseCatalogList.forEach(e -> {
                        if (DataUtil.idIsNotNull(e.getMaterialId())) {
                            CouMaterial material = materialMaps.get(e.getMaterialId());
                            e.setMaterial(material);
                        }
                    });
                }
            }
        }
        return courseCatalogList;
    }

    /**
     * 设置直播目录播放状态
     *
     * @param courseCatalogList
     * @return List<CourseCatalog>
     */
    private List<CourseCatalog> setLiveCatalogPlayStatus(List<CourseCatalog> courseCatalogList) {
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            Map<Boolean, List<CourseCatalog>> courseCatalogListMap = courseCatalogList.stream().filter(e -> StringUtils.isNotEmpty(e.getMaterialTypeKey())).collect(Collectors.groupingBy(e -> e.getMaterialTypeKey().equals(MaterialType.TYPE_KEY_LIVE.getKey())));
            List<CourseCatalog> liveCourseCatalogList = courseCatalogListMap.get(true);//获取直播类型的目录
            if (ObjectUtils.isNotEmpty(liveCourseCatalogList)) {
                Date currentTime = new Date();
                liveCourseCatalogList.forEach(e -> {
                    Date lessonStartTime = e.getLessonStartTime();
                    Date lessonEndTime = e.getLessonEndTime();
                    if (lessonStartTime.before(currentTime) && lessonEndTime.after(currentTime)) {
                        e.setLivePlayState(1);//直播中
                    }
                    if (lessonStartTime.after(currentTime)) {
                        e.setLivePlayState(2);//未开始
                        //是否可以提前进入（单位/分）
                        if (ObjectUtils.isNotEmpty(e.getMaterial())) {
                            int preEnterTime = e.getMaterial().getPreEnterTime();
                            //距离开始还有多少时间（毫秒）
                            long time = lessonStartTime.getTime() - System.currentTimeMillis();
                            if (!(time > (preEnterTime * 60 * 1000))) {//距离时间大于提前进入时间，则提示未开始
                                e.setLivePlayState(4);
                            }
                        }
                    }
                    if (lessonEndTime.before(currentTime)) {
                        e.setLivePlayState(3);//已结束
                    }
                });
            }
        }
        return courseCatalogList;
    }

    /**
     * 修改课程 service
     *
     * @param courseCatalog 章节
     * @param type          1修改 2 添加时旧章节可以为空 3删除
     */
    private void updateCourseService(CourseCatalog courseCatalog, int type) {

        if (courseCatalog.getNodeType() != 2) {
            return;
        }
        //如果修改或保存的课程目录包含随堂资料或者随堂练习直接  1 配套练习  2 学习资料 3 全部显示
        Integer service = 0;

        if (StringUtils.isNotEmpty(courseCatalog.getQuestionIds()) && ObjectUtils.isNotEmpty(courseCatalog.getDatums())) {
            service = 3;
        } else if (StringUtils.isNotEmpty(courseCatalog.getQuestionIds())) {
            service = 1;
        } else if (ObjectUtils.isNotEmpty(courseCatalog.getDatums())) {
            service = 2;
        }

        List<String> containColumns = new ArrayList<>();
        containColumns.add("service");
        containColumns.add("id");
        Course course = courseBiz.findById(courseCatalog.getCourseId(), containColumns);
        Integer _service = course.getService();
        if (type == 1 && service == 0) {
            return;
        } else if (service == 0) {
            //检查其它目录是否存在随堂资料 和 随堂练习
            HashMap<String, Object> datumsAndQuestionNum = courseCatalogDao.findDatumsAndQuestionNum(CourseCatalog.class, courseCatalog.getCourseId());
            if (Integer.valueOf(datumsAndQuestionNum.get("question").toString()) != 0 && Integer.valueOf(datumsAndQuestionNum.get("datum").toString()) != 0) {
                service = 3;
            } else if (Integer.valueOf(datumsAndQuestionNum.get("question").toString()) == 1) {
                service = 1;
            } else if (Integer.valueOf(datumsAndQuestionNum.get("datum").toString()) == 1) {
                service = 2;
            }
        }
        if (service == _service) {
            return;
        } else if ((service == 3 && _service != 3) || (service == 1 && _service == 2) || (service == 2 && _service == 1)) {
            course.setService(3);
        } else {
            course.setService(service);
        }
        courseBiz.updateById(course, null);
    }

    /**
     * 动态添加讲师
     *
     * @param courseCatalogs
     * @param courseId
     * @param type
     */
    private void updateCourseTeacher(List<CourseCatalog> courseCatalogs, BigDecimal courseId, Integer type) {
        String materialIds = courseCatalogs.stream().filter(e -> ObjectUtils.isNotEmpty(e.getMaterialId()) && e.getNodeType() == 2).map(e -> e.getMaterialId().toString()).collect(Collectors.joining(","));
        if (StringUtils.isEmpty(materialIds)) {
            return;
        }
        List<String> containColumns = new ArrayList<>();
        containColumns.add("teacherId");
        List<CouMaterial> couMaterials = couMaterialBiz.find("id in (" + materialIds + ")", null, containColumns);
        containColumns.clear();
        containColumns.add("teacherIds");
        containColumns.add("id");
        Course course = courseBiz.findById(courseId, containColumns);
        String getTeacherIds = couMaterials.stream().filter(e -> ObjectUtils.isNotEmpty(e.getTeacherId())).map(e -> e.getTeacherId().toString()).collect(Collectors.joining(","));
        if (type == 1) {
            setCourseTeacher(getTeacherIds, course);
        } else if (type == 2) {
            deleteCourseTeacher(getTeacherIds, course);

        }
    }

    /**
     * 添加讲师
     *
     * @param getTeacherIds
     * @param course
     */
    private void setCourseTeacher(String getTeacherIds, Course course) {
        List<String> strings = new ArrayList<>();
        if (StringUtils.isEmpty(course.getTeacherIds())) {
            strings.addAll(Arrays.asList(getTeacherIds.split(",")));
        } else {
            String[] teacherIds = StringUtils.subHeadTailString(course.getTeacherIds(), ",").split(",");
            String[] _teacherIds = getTeacherIds.split(",");
            strings.addAll(Arrays.asList(teacherIds));
            strings.addAll(Arrays.asList(_teacherIds));
        }
        TreeSet<String> hset = new TreeSet<String>(strings);
        StringBuffer teacherIds = new StringBuffer(String.join(",", hset));
        teacherIds.insert(0, ",");
        teacherIds.append(",");
        course.setTeacherIds(teacherIds.toString());
        courseBiz.updateById(course, null);
    }

    /**
     * 删除讲师
     *
     * @param getTeacherIds
     * @param course
     */
    private void deleteCourseTeacher(String getTeacherIds, Course course) {
        String _teacherIds = course.getTeacherIds();
        if (StringUtils.isEmpty(_teacherIds)) {
            return;
        }
        _teacherIds = StringUtils.subHeadTailString(_teacherIds, ",");
        String[] courseTeacherId = _teacherIds.split(",");
        String[] couMaterialsTeacherIds = getTeacherIds.split(",");
        List<String> courseTeacherIds = Arrays.asList(courseTeacherId);
        List arrList = new ArrayList(courseTeacherIds);
        for (String teacherId : couMaterialsTeacherIds) {
            if (arrList.contains(teacherId)) {
                arrList.remove(teacherId);
            }
        }
        if (arrList.size() > 0) {
            StringBuffer teacherIds = new StringBuffer(String.join(",", arrList));
            teacherIds.insert(0, ",");
            teacherIds.append(",");
            course.setTeacherIds(teacherIds.toString());
            courseBiz.updateById(course, null);
        } else {
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", course.getId());
            map.put("columnName", "teacherIds");
            courseBiz.updateCourseColumnNull(map);
        }
    }

    public Integer queryCurrentCount(Map<String, Object> map) {
        return courseCatalogDao.queryCurrentCount(CourseCatalog.class, map);
    }

    public List<CourseCatalog> findCourseCatalogPage(CourseCatalog courseCatalog) {
        List<CourseBuyRecord> courseBuyRecords = courseBuyRecordBiz.find("userId = " + courseCatalog.getUserId() + " and courseStatus = 'SUCCESS'", 0, null);
        if (ObjectUtils.isEmpty(courseBuyRecords)){
            return  new ArrayList<>(0);
        }
        String packageIds = courseBuyRecords.parallelStream()
                .filter(courseBuyRecord -> !
                        CourseType.COURSE_TYPE_COLUMNS.equals(courseBuyRecord.getCourseTypeKey()) || CourseType.COURSE_TYPE_PACKAGE.equals(courseBuyRecord.getCourseTypeKey() ))
                .map(courseBuyRecord -> courseBuyRecord.getCourseId().toString()).collect(Collectors.joining(","));

        Stream<String> courseIdTemps= courseBuyRecords.parallelStream()
                .filter(courseBuyRecord -> !CourseType.COURSE_TYPE_COLUMNS.equals(courseBuyRecord.getCourseTypeKey()) || !CourseType.COURSE_TYPE_PACKAGE.equals(courseBuyRecord.getCourseTypeKey()))
                .map(courseBuyRecord -> courseBuyRecord.getCourseId().toString());
        List<PackageCourse> packageCourses = new ArrayList<>(0);
        if (StringUtils.isNotEmpty(packageIds)){
            packageCourses = packageCourseBiz.find("packageId in  (" + packageIds + ")", 0, null);
        }
        // 课程所属的套餐id
        Map<BigDecimal, List<PackageCourse>> packageCourseIdMap = packageCourses.stream().collect(Collectors.groupingBy(e -> e.getCourseId()));
        //套餐下的课程ID
        Stream<String> packageCourseIds = packageCourses.parallelStream().map(PackageCourse::getCourseId).distinct().map(bigDecimal -> bigDecimal.toString());
        List<String> courseIds= Stream.concat(courseIdTemps, packageCourseIds).distinct().collect(Collectors.toList());
        if (ObjectUtils.isEmpty(courseIds)){
            courseIds = Lists.newArrayList("0");
        }
        //根据查询出的套餐ID查询套餐下的课程
        List<CourseCatalog> courseCatalogList = courseCatalogDao.queryLiveCourseListNodes(CourseCatalog.class, courseCatalog,courseIds);
        setCourseCatalogData(courseCatalogList);
        handlingTimeAxis(courseCatalogList);
        courseCatalogList.stream().forEach(e->{
            List<PackageCourse> packageCourses1 = packageCourseIdMap.get(e.getCourseId());
            if (ObjectUtils.isNotEmpty(packageCourses1)) {
                e.setPackageId(packageCourses1.get(0).getPackageId());
            }
        });
        this.setMaterialData(courseCatalogList, true);
        this.setLiveCatalogPlayStatus(courseCatalogList);
        return courseCatalogList;


        /*List<CourseCatalog> courseCatalogList = courseCatalogDao.queryLiveCourseListNodes(CourseCatalog.class, courseCatalog);
        setCourseCatalogData(courseCatalogList);
        handlingTimeAxis(courseCatalogList);
        return courseCatalogList;*/
    }

    /**
     * 设置节点数据
     *
     * @param catalogList
     */
    private void setCourseCatalogData(List<CourseCatalog> catalogList) {
        if (ObjectUtils.isNotEmpty(catalogList)) {
            String catalogIds = catalogList.stream().map(c -> c.getParentId().toString()).distinct().collect(Collectors.joining(","));
            List<CourseCatalog> courseCatalogs = this.find(" id in(" + catalogIds + ")", null, null);
            Map<BigDecimal, CourseCatalog> catalogMap = courseCatalogs.stream().collect(Collectors.toMap(c -> c.getId(), c -> c));
            catalogList.forEach(c -> {
                if (ObjectUtils.isNotEmpty(catalogMap.get(c.getParentId()))) {
                    c.setParentName(catalogMap.get(c.getParentId()).getCatalogName());
                }
            });


        }
    }

    /**
     * 设置时间轴
     *
     * @param courseCatalogList
     * @return
     */
    private List<CourseCatalog> handlingTimeAxis(List<CourseCatalog> courseCatalogList) {
        if (ObjectUtils.isNotEmpty(courseCatalogList)) {
            courseCatalogList.forEach(c->{
                StringBuffer lessonStart =new  StringBuffer(DateUtils.format(c.getLessonStartTime(), "MM.dd HH:mm"));
                StringBuffer lessonEnd =new  StringBuffer(DateUtils.format(c.getLessonEndTime(), "dd"));
                c.setLessonTimeFormat(lessonStart.insert(5,"-"+lessonEnd).toString());
            });


            Map<String, List<CourseCatalog>> courseCatalogMap = courseCatalogList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getLessonStartTime(), "yyyy")));
            List<CourseCatalog> _list = new ArrayList<>();
            courseCatalogMap.forEach((k, v) -> {
                String str = k;
                if (DateUtils.format(new Date(), "yyyy").equals(k)) {
                    str = "今天";
                } else {
                    str = str + "年";
                }
                v.get(0).setTimeAxis(str);
                _list.addAll(v);
            });
            return _list;
        }
        return courseCatalogList;
    }

    /**
     * 获取查询SQL
     *
     * @param condition 查询条件对象
     * @return 处理后的条件
     */
    private String getWhereSql(CourseCatalogCondition condition) {
        StringBuilder whereSql = new StringBuilder(" 1=1");
        if (ObjectUtils.isNotEmpty(condition)) {
            if (DataUtil.idIsNotNull(condition.getCourseId())) {
                whereSql.append(" and courseId = ").append(condition.getCourseId());
            }
            if (StringUtils.isNotEmpty(condition.getCourseIds())) {
                whereSql.append(" and courseId in (").append(condition.getCourseIds()).append(")");
            }
            if (StringUtils.isNotEmpty(condition.getQueryIds())) {
                whereSql.append(" and id in (").append(condition.getQueryIds()).append(")");
            }
            if (DataUtil.idIsNotNull(condition.getMouldId())) {
                whereSql.append(" and mouldId = ").append(condition.getMouldId());
            }
            if (condition.isNotParentId()) {
                whereSql.append(" and (parentId <= 0 or parentId is null)");
            }
            if (DataUtil.isPositive(condition.getAudition())) {
                whereSql.append(" and audition = ").append(condition.getAudition());
            }
            if (StringUtils.isNotEmpty(condition.getMaterialIds())) {
                whereSql.append(" and materialId in (").append(condition.getMaterialIds()).append(")");
            }
            if (condition.isNowUpload()) {
                whereSql.append(" and (materialId is null or materialId =0) and lessonTime is not null and lessonTime like '").append(DateUtils.format(new Date(), "yyyy-MM-dd")).append("%'");
            }
        }
        whereSql.append(" order by sort asc,id asc");
        return whereSql.toString();
    }
}
